home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1993, 1995, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
-
- /* csg.c
- * This program demonstrate constructive solid geometry.
- *
- * Escape key - exit the program
- * <r> key - toggle rotation
- */
- #include <GL/gl.h>
- #include <GL/glu.h>
- #include <GL/glut.h>
-
- #include <math.h>
- #include <stdio.h>
-
- /* Function Prototypes */
-
- GLvoid initgfx( GLvoid );
- GLvoid drawScene( GLvoid );
- GLvoid reshape( GLsizei, GLsizei );
- GLvoid animate( GLvoid );
- GLvoid visibility( GLint );
- GLvoid keyboard( GLubyte, GLint, GLint );
-
- GLvoid drawCylinder( GLint );
- GLvoid screenRectangle( GLvoid );
- GLvoid solidCylinder( GLfloat, GLfloat, GLint );
-
- void printHelp( char * );
-
- /* Global Definitions */
-
- #define KEY_ESC 27 /* ascii value for the escape key */
-
- /* Global Variables */
-
- static GLfloat fovy = 60.0; /* Field of view in Y angle */
- static GLfloat near = 3.0; /* Near clipping plane location */
- static GLfloat far = 13.0; /* Far clipping plane location */
-
- static GLfloat spin = 0.0;
-
- void
- main(int argc, char *argv[])
- {
- GLsizei width, height;
-
- glutInit( &argc, argv );
-
- width = glutGet( GLUT_SCREEN_WIDTH );
- height = glutGet( GLUT_SCREEN_HEIGHT );
- glutInitWindowPosition( width/4, height/4 );
- glutInitWindowSize( width/2, height/2 );
- glutInitDisplayMode( GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE|GLUT_STENCIL );
- glutCreateWindow( argv[0] );
-
- initgfx();
-
- glutKeyboardFunc( keyboard );
- glutReshapeFunc( reshape );
- glutIdleFunc( animate );
- glutVisibilityFunc( visibility );
- glutDisplayFunc( drawScene );
-
- printHelp( argv[0] );
-
- glutMainLoop();
- }
-
- void
- printHelp( char *progname )
- {
- fprintf(stdout, "%s -- demonstrates how to use the stencil planes\n"
- "to perform constructive solid geometry\n\n"
- "Escape key - exit the program\n"
- "<r> key - toggle rotation\n\n", progname);
- }
-
- /* Initialize material properties, light source, lighting model, etc. */
- GLvoid
- initgfx( GLvoid )
- {
- GLfloat mat_ambient[] = { 0.25, 0.05, 0.4, 1.0 };
- GLfloat mat_diffuse[] = { 0.5, 0.1, 0.8, 1.0 };
- GLfloat mat_diffuse_back[] = { 1.0, 1.0, 0.0, 1.0 };
- GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
- GLfloat mat_shininess[] = { 10.0 };
- GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
-
- glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
- glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
- glMaterialfv(GL_BACK, GL_DIFFUSE, mat_diffuse_back);
- glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
- glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
- glLightfv(GL_LIGHT0, GL_POSITION, light_position);
-
- glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
-
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
-
- glEnable( GL_DEPTH_TEST );
- }
-
- GLvoid
- keyboard( GLubyte key, GLint x, GLint y )
- {
- static GLboolean rotating = GL_TRUE;
-
- switch (key) {
- case 'r': /* toggle rotation */
- rotating = !rotating;
- if (rotating)
- glutIdleFunc( animate );
- else
- glutIdleFunc( NULL );
- break;
- case KEY_ESC: /* Exit whenever the Escape key is pressed */
- exit(0);
- }
- }
-
- GLvoid
- reshape( GLsizei width, GLsizei height )
- {
- glViewport( 0, 0, width, height );
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
- gluPerspective( fovy, (GLdouble) width / (GLdouble) height, near, far );
- glMatrixMode( GL_MODELVIEW );
- gluLookAt( 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
- }
- GLvoid
- animate( GLvoid )
- {
- spin = fmodf( spin + 3.0, 360.0 ); /* update spin */
- glutPostRedisplay(); /* Tell GLUT to redraw */
- }
-
- GLvoid
- visibility( int state )
- {
- if (state == GLUT_VISIBLE) {
- glutIdleFunc( animate );
- } else {
- glutIdleFunc( NULL );
- }
- }
-
- /* solidCylinder -- draws a filled cylinder. If the closed flag
- * is set, it cap the ends, making it a closed cylinder.
- * The glutSolidCylinder routine is not appropriate here because
- * it does not cap its ends.
- */
- #define NSEG 20
- #define TP (2.*M_PI) /* 2*pi */
-
- GLvoid
- solidCylinder( GLfloat radius, GLfloat length, GLint closed )
- {
- GLfloat circleCoords[NSEG][2], n[NSEG][3];
- int i;
-
- /* define circle coords and draw sides of cylinder */
- glBegin (GL_QUAD_STRIP);
- for (i=0; i<NSEG; i++) {
- n[i][0] = sinf((float)i/NSEG*TP);
- n[i][1] = cosf((float)i/NSEG*TP);
- n[i][2] = 0;
- circleCoords[i][0] = n[i][0] * radius;
- circleCoords[i][1] = n[i][1] * radius;
- glNormal3fv( n[i] );
- glVertex3f( circleCoords[i][0], circleCoords[i][1],
- -length/2.0 );
- glVertex3f( circleCoords[i][0], circleCoords[i][1],
- length/2.0 );
- }
- glNormal3fv(n[0] );
- glVertex3f( circleCoords[0][0], circleCoords[0][1],
- -length/2.0 );
- glVertex3f( circleCoords[0][0], circleCoords[0][1],
- length/2.0 );
- glEnd();
-
- if ( closed ) {
- /* draw bottom (-z) end of cylinder */
- glNormal3f(0, 0, -1);
- glBegin (GL_POLYGON);
- for(i=0; i<NSEG; i++) {
- glVertex3f( circleCoords[i][0], circleCoords[i][1],
- -length/2.0 );
- }
- glEnd();
-
- /* other end of cylinder */
- glNormal3f(0, 0, 1);
- glBegin (GL_POLYGON);
- for(i=0; i<NSEG; i++) {
- glVertex3f( circleCoords[NSEG-1-i][0],
- circleCoords[NSEG-1-i][1], length/2.0 );
- }
- glEnd();
- }
- }
-
- GLvoid
- drawCylinder( GLint closed )
- {
- glPushMatrix();
- glRotatef( 90, 0.0, 0.0, 1.0 );
- solidCylinder( 0.3, 2.0, closed );
- glPopMatrix();
- }
-
- /* draw a rectangle the size of the screen */
- GLvoid
- screenRectangle( GLvoid )
- {
- GLint viewport[4];
-
- glGetIntegerv( GL_VIEWPORT, viewport );
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode( GL_PROJECTION );
- glPushMatrix();
- glLoadIdentity();
- gluOrtho2D(0, viewport[2], 0, viewport[3] );
- glRecti( 0, 0, viewport[2], viewport[3] );
- glPopMatrix();
- glMatrixMode( GL_MODELVIEW );
- glPopMatrix();
- }
-
- GLvoid
- drawScene( GLvoid )
- {
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
- GL_STENCIL_BUFFER_BIT );
-
- glPushMatrix();
- glRotatef( spin, 0.0, 1.0, 0.0 );
-
- /* disable writing to color planes until we're ready to draw */
- glColorMask ( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
-
- /* render the front faces of the tetrahedron into the depth planes,
- * capturing the depth info
- */
-
- glCullFace( GL_BACK );
- glEnable( GL_CULL_FACE );
- glDepthFunc( GL_LESS ); /* reset to default depth test */
- glutSolidTetrahedron();
-
-
- /* increment the stencil planes whereever either face
- * (front or back) of the cylinder is in front of the tetra
- * (the depth test passes), but don't update the depth buffer.
- */
-
- glEnable( GL_STENCIL_TEST );
- glStencilFunc( GL_ALWAYS, 0, 0xff );
- glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
- glDepthMask( 0 );
- glDisable( GL_CULL_FACE );
- drawCylinder( 1 );
- glDepthMask( 1 ); /* reenable writing to the depth buffer */
-
- /* force depth values to max value wherever the cylinder is inside
- * the tetra (wherever the stencil planes have a value of one)
- */
-
- glStencilFunc( GL_EQUAL, 1, 0xff );
- glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
- glDepthFunc( GL_ALWAYS );
- glDepthRange( 1.0, 1.0 );
- screenRectangle(); /* draw rectangle size of screen */
- glDepthRange( 0.0, 1.0 );
-
- /* render back faces of the tetra and the (uncapped) cylinder
- * into depth buffer where the hole is (the stencil test is
- * still active). This will keep the cylinder from sticking
- * outside the tetra.
- */
-
- glCullFace( GL_FRONT );
- glEnable( GL_CULL_FACE );
- glDepthFunc( GL_LESS );
- glutSolidTetrahedron();
- drawCylinder( 0 );
-
- /* now draw -- enable writing to the color bitplanes and
- * set the depth test to pass only if the incoming z equals
- * the stored z. Turn off the stencil test.
- */
-
- glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
- glDisable( GL_STENCIL_TEST );
- glCullFace( GL_BACK );
- glDepthFunc( GL_EQUAL );
- glutSolidTetrahedron();
-
- /* draw the back faces of the cylinder because we want to
- * see the inside of it.
- */
-
- glCullFace( GL_FRONT );
- drawCylinder( 0 );
-
- glPopMatrix();
-
- glutSwapBuffers();
- }
-